
#################################################################
# Imports
#################################################################
import os
import os.path
from PIL import Image

#################################################################
# Constants
#################################################################
rs = Image.ANTIALIAS #Resample type, aliased for conveniance 


##################################################################
#Functions
##################################################################

def absResize(img, sizeTuple):
    """Simple call to Img.Resize.  Straight passthrough.
    Exists in order to more easily incorporate into a dictionary
    of functions that expects to take an image as a paramater."""

    return img.resize(sizeTuple, rs)

def maxResize(img, maxSizeTuple):
    """Takes an image and a maximum size tuple.
    It then adjusts the images size to the maximum size that is less than
    or equal to the sizeTuple and maintains the previous aspect ratio."""
    minRatio = min(
                    float(maxSizeTuple[0])/float(img.size[0]),
                    float(maxSizeTuple[1])/float(img.size[1])
                    )
    #int will automatically take the floor of the value
    sizeTuple = (
                    int(img.size[0] * minRatio),
                    int(img.size[1] * minRatio)
                )
    return img.resize(sizeTuple, rs)

def pctResize(img, pct):
    """Takes an image and a percentage and returns a reference to an
    image that has been scaled by that percentage."""
    pct = pct/100.0
    #int will automatically take the floor of the value
    sizeTuple = (
                    int(img.size[0] * pct),
                    int(img.size[1] * pct)
                )
    return img.resize(sizeTuple, rs)

def adjName(path, name, prefix='', suffix = ''):
    """Takes a file name, inserts the suffix before the extension and/or
    the prefix at the beginning, then adds the path and returns.
    """
    if len(prefix) != 0:
        name = prefix + name
        
    if len(suffix) != 0:
        period = name.rindex('.')
        name = name[0:period] + suffix + name[period:]

    return os.path.join(path, name)

def processFolder(inFolder, adj, adjType, outFolder='', prefix='', suffix = ''):
    """Processes the passed in folder.  It requires the folder to process, the
    value to adjust too, and the adjustment type.  The expected value type for
    ajd depends on the adjustment type.  For max or abs it is looking for a two
    tuple of numbers.  For pct it is looking for a single number.
    It returns a list of the file names that could not be processed.

    Optionally, it will take an output folder, a pre/suf-fix to add and a 0 indicating a
    prefix or 1 indicating a suffix.  If the outFolder is the same as the inFolder
    and no pre/suf-fix is supplied, it will overwrite all image files in that folder."""
    couldNotProcess = []
    if len(outFolder) == 0 :
        outFolder = inFolder
    for file in [x for x in os.listdir(inFolder) if
                 os.path.isfile(os.path.join(inFolder,x))]:
        try:
            img = Image.open(os.path.join(inFolder,file))
            img = {'abs': absResize,
                   'max': maxResize,
                   'pct': pctResize}[adjType](img, adj)
            newFileName = adjName(outFolder, file, prefix, suffix)
            img.save(newFileName)
        except Exception, inst:
            couldNotProcess.append(file)
            #send the reason to console for troubleshooting, end user should not see if
            #run under a gui.
            print 'Failed on : ' + file
            print inst
            print '\n'
    return couldNotProcess

##################################################################
#Main loop.
#Normally this will be brought in as a library with a gui, but this 
#provides, a CLI for testing or use without a gui.
##################################################################
if __name__=="__main__":
    #set up the option parser
    from optparse import OptionParser #command line paramaters, only needed if this is main

    usage = "usage: %prog [options]"
    parser = OptionParser()
    parser.add_option("-i", "--inFolder", dest = "inFolder",
                      help = "Folder to process, defaults to current folder",
                      default = os.path.abspath(''))
    parser.add_option("-a", "--adj", dest = "adj",
                      help = """Adjustment, either (len, width) with parenthesis
                              or percent, default (640, 480)""",
                      default = '(640, 480)')
    parser.add_option("-t", "--adjType", dest = "adjType",
                      help = "pct, max, abs",
                      default = "max")
    parser.add_option("-o", "--outFolder", dest = "outFolder",
                      help = "out folder path",
                      default = "") #if left out, it will go to the inFolder
    parser.add_option("-p", "--prefix", dest = "prefix",
                      help = "Prefix to attach at beginning",
                      default = "")
    parser.add_option("-s", "--suffix", dest = "suffix",
                      help = "Suffix to attach at end",
                      default = "")
        
    (options, args) = parser.parse_args()    

    #adj  should not be strings, so must be parsed
    try:
        if options.adj[0] + options.adj[-1] == '()':
            adj = tuple(map(float, options.adj[1:-1].split(',')))
        else:
            adj = float(options.adj)

    except Exception, inst:
        print 'Improper options'
        print inst        

    print 'adj = '
    print adj
    couldNotProcess = processFolder(options.inFolder, adj, options.adjType,
                                    options.outFolder, options.prefix, 
                                    options.suffix)

    if len(couldNotProcess) > 0:
        print "Completed, but could not process:"
        print ', \n'.join(couldNotProcess)
    else:
        print "Done"
    

        
        
    
